package com.wt.router;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @Auther: wtt
 * @Date: 2022/1/22 12:39
 * @Description:
 */
public class ReadRestartInstance implements PathChildrenCacheListener {

    private static final Logger LOGGER = LoggerFactory.getLogger(ReadRestartInstance.class);
    private static final String LISTEN_PATH = "/wt/dubbo/restart/instances";
    private final CuratorFramework zkClient;
    // 重启机器的机器列表
    private volatile Set<String> restartInstances = new HashSet<>();

    private ReadRestartInstance(CuratorFramework zkClient) {
        this.zkClient = zkClient;
    }

    public static ReadRestartInstance create() {
        final CuratorFramework zookeeperClient = ZookeeperClient.getClient();
        try {
            final Stat stat = zookeeperClient.checkExists().forPath(LISTEN_PATH);
            if (null == stat) {
                zookeeperClient.create().creatingParentsIfNeeded().forPath(LISTEN_PATH);
            }
        } catch (Exception e) {
            LOGGER.error("确保基础路径存在,path:{}", LISTEN_PATH, e);
        }
        ReadRestartInstance instance = new ReadRestartInstance(zookeeperClient);
        PathChildrenCache childrenCache = new PathChildrenCache(zookeeperClient, LISTEN_PATH, false);
        childrenCache.getListenable().addListener(instance);
        try {
            childrenCache.start();
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.error("启动路径监听失败，path:{}", LISTEN_PATH, e);
        }
        return instance;
    }

    public String buildApplicationInstance(String application, String host) {
        return String.format("%s_%s", application, host);
    }

    public void addRestartInstance(String application, String host) throws Exception {
        zkClient.create().creatingParentContainersIfNeeded()
                .forPath(LISTEN_PATH + "/" + buildApplicationInstance(application, host));
    }

    public void removeRestartInstance(String application, String host) throws Exception {
        zkClient.delete()
                .forPath(LISTEN_PATH + "/" + buildApplicationInstance(application, host));
    }

    public boolean hasRestartingInstance(String application, String host) {
        return restartInstances.contains(buildApplicationInstance(application, host));
    }


    @Override
    public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
        final List<String> restartingInstances = zkClient.getChildren().forPath(LISTEN_PATH);
        if (!CollectionUtils.isEmpty(restartingInstances)) {
            this.restartInstances = new HashSet<>(restartingInstances);
        } else {
            this.restartInstances = Collections.emptySet();
        }
    }
}
